<template>
	<view class="vi_year">
		<view class="vi_year_head" :style="headStyle">
			<view class="iconfont" :class="prevCls" @click="turnPage(-1)"></view>
			<view :class="titleClass||''" @click="headClick">
				<text>{{inList[0].value}}</text>
				<text class="vi_mx">-</text>
				<text>{{inList[inList.length-1].value}}</text>
			</view>
			<view class="iconfont" :class="nextCls" @click="turnPage(1)"></view>
		</view>
		<view class="vi_year_body">
			<!-- 选择列表 -->
			<vi-drawer ref="selectList" position="absolute" width="60%" v-if="setting.mode=='checkbox'">
				<scroll-view class="vi_year_selectList" scroll-y @touchmove.stop>
					<view class="vi_year_selectItem" v-for="(item, index) in inValue" :key="index">
						<!-- 标题 -->
						<view class="">
							{{item}}
						</view>
						<!-- 删除按钮 -->
						<view @click="delItem(item)">
							<vi-style-controller
								type="bgError"
								radius="circle"
								width="1.2em"
								height="1.2em"
								:disabled="disabled"
								:readOnly="readOnly"
								borderBox
								active>
								<text class="iconfont" :class="iconSetting.delete"></text>
							</vi-style-controller>
						</view>
					</view>
				</scroll-view>
			</vi-drawer>
			
			<view class="vi_year_list">
				<view class="vi_year_itembox" :style="itemStyle" v-for="(item, index) in inList" :key="index">
					<!-- 背景 -->
					<view class="vi_year_actBg" :style="{'opacity':setting.rangeBgOpacity}" v-if="setting.mode=='range'&&item.bgAct">
						<vi-style-controller
							compName="calendarDate"
							:type="setting.type"
							:color="color"
							:radius="item.bgRadius"
							:size="setting.size"
							width="100%"
							:height="setting.rowHeight"
							:disabled="item.disabled||disabled"
							:readOnly="item.readOnly||readOnly"
							active>
						</vi-style-controller>
					</view>
					<view class="vi_year_item">
						<vi-style-controller @click="onClick(item.value)"
							compName="calendarDate"
							:type="setting.type"
							:color="color"
							:textColor="textColor"
							:radius="item.radius"
							:size="setting.size"
							:plain="plain||(!item.act&&item.value==thisYear)"
							:borderWidth="plain?1:0"
							:borderColor="item.borderColor"
							width="100%"
							:height="setting.rowHeight"
							:disabled="item.disabled||disabled"
							:readOnly="item.readOnly||readOnly"
							borderBox
							:active="item.act||item.value==thisYear">
							<text>{{item.name}}</text>
						</vi-style-controller>
					</view>
				</view>
			</view>
		</view>
		
		<view class="vi_year_tips" v-if="setting.useToolbar">
			<view class="vi_year_text">
				<view v-if="setting.mode!='checkbox'">
					<text>{{textSetting.yearSelected}}：</text>
				</view>
				<vi-style-controller v-else @click="showSelectList"
					control="text"
					:type="setting.type"
					:color="color"
					:disabled="!inValue.length"
					active>
					<text>{{textSetting.yearSelected}}({{inValue.length}})：</text>
				</vi-style-controller>
			</view>
			<view class="vi_month_info" v-if="setting.mode=='radio'">
				<text>{{inValue[0]}}</text>
			</view>
			<view class="vi_month_info" v-else-if="setting.mode=='checkbox'">
				<text class="vi_inlineBlock" v-for="(val, index) in inValue" :key="index">{{(index>0?"、":"")+val}}</text>
			</view>
			<view class="vi_month_info" v-else-if="setting.mode=='range'">
				{{inValue[0] ||""}}
				<text class="vi_mx" v-if="inValue.length==2">-</text>
				{{inValue[1] ||""}}
			</view>
		</view>
		
		<view class="vi_calendar_submitBtn" v-if="setting.useSubmit">
			<vi-button @click="submit"
				:type="setting.type"
				:color="color"
				:textColor="textColor"
				:radius="setting.submitRadius"
				:size="setting.submitSize"
				:plain="submitPlain"
				:width="setting.submitWidth"
				:height="submitHeight"
				:disabled="disabled||disabledSubmit"
				:readOnly="readOnly">{{textSetting.confirm}}</vi-button>
		</view>
	</view>
</template>

<script>
	export default {
		name:"viYear",
		model:{
			prop:"value",
			event:"input"
		},
		props: {
			type:{
				type:[String,null],
				default:null
			},
			color:{
				type:[String,null],
				default:""
			},
			textColor:{
				type:[String,null],
				default:""
			},
			radius:{
				type:[String,Number,null],
				default:null
			},
			size:{
				type:[String,null],
				default:null
			},
			plain:{
				type:[Boolean,null],
				default:false
			},
			titleHeight:{
				type:[String,null],
				default:""
			},
			rowHeight:{
				type:[String,null],
				default:""
			},
			rowSpace:{
				type:[Number,null],
				default:null
			},
			rangeBgOpacity:{
				type:[Number,null],
				default:null
			},
			//选择类型，radio单选、checkbox多选、range选区
			mode:{
				type:[String,null],
				default:""
			},
			page:{
				type:[Number,null],
				default:0
			},
			value:{},	//当前值，作为基准时间，必须是合法的时间值
			row:{
				type:[Number,null],
				default:0
			},
			column:{
				type:[Number,null],
				default:0
			},
			titleClass:{
				type:[String,null],
				default:""
			},
			iconClass:{
				type:[String,null],
				default:""
			},
			start:{
				type:[Number,String,null],
				default:""
			},
			end:{
				type:[Number,String,null],
				default:""
			},
			min:{
				type:[Number,null],
				default:null
			},
			max:{
				type:[Number,null],
				default:0
			},
			disabled:{
				type:[Boolean,null],
				default:false
			},
			readOnly:{
				type:[Boolean,null],
				default:false
			},
			useToolbar:{
				type:[Boolean,null],
				default:null
			},
			//提交按钮
			useSubmit:{
				type:[Boolean,null],
				default:null
			},
			submitWidth:{
				type:[String,null],
				default:null
			},
			submitRadius:{
				type:[String,Number,null],
				default:null
			},
			submitSize:{
				type:[String,null],
				default:null
			},
			submitPlain:{
				type:[Boolean,null],
				default:false
			},
			submitHeight:{
				type:[Number,String,null],
				default:""
			},
			icon:{
				type:[Object,null],
				default:()=>({})
			},
			text:{
				type:[Object,null],
				default:()=>({})
			},
		},
		data() {
			return {
				inList:[],		//数据列表
				inPage:0,		//页码，用于生成列表
				origin:0,		//起始基准点
				inValue:[],		//选中
				thisYear:null,	//今年
				dicIcon:{
					prevYear: "icon-arr-double-left",
					nextYear: "icon-arr-double-right",
					delete: "icon-delete-small",
				},
				dicText:{
					confirm: "确定",
					yearSelected: "已选",
					thisYear: "今年",
					tipYearEmptyError: "请选择一个选项",
					tipYearMinError: "请至少选择{$min}个选项",
					tipYearMaxError: "请选择{$min}至{$max}个选项",
					tipYearRangeError: "请选择选项范围",
				},
			}
		},
		computed: {
			setting(){
				return {
					type: this.$api.isDefined(this.type)? this.type :"primary",
					mode: this.mode ||"radio",
					rangeBgOpacity: this.$api.isValue(this.rangeBgOpacity)? this.rangeBgOpacity :0.1,
					min: this.$api.isValue(this.min)? this.min :1,
					size: this.$api.isDefined(this.size)? this.size :"md",
					titleHeight: this.titleHeight ||"2.5em",
					rowHeight: this.rowHeight ||"2.5em",
					radius: this.$api.isDefined(this.radius)? this.radius :"0.25em",
					rowSpace: this.$api.isValue(this.rowSpace)? this.rowSpace :0.2,
					useToolbar: this.$api.isBoolean(this.useToolbar)? this.useToolbar :true,
					useSubmit: this.$api.isBoolean(this.useSubmit)? this.useSubmit :true,
					submitSize: this.$api.isDefined(this.submitSize)? this.submitSize :"md",
					submitRadius: this.$api.isDefined(this.submitRadius)? this.submitRadius :"circle",
					submitWidth: this.$api.isDefined(this.submitWidth)? this.submitWidth :"100%",
					row: this.row ||5,
					column: this.column ||3,
				}
			},
			defStart(){
				let st = this.start ||0,
					len = String(st).length;
				if(len>4){//长度大于4认为是时间值，小于4是无效值
					st = this.$api.isNumber(st, true)? Number(st) :st;
					st = new Date(st).getFullYear();
				}else if(len<4){
					st =0
				}
				return st
			},
			defEnd(){
				let ed = this.end ||Infinity,
					len = String(ed).length;
				if(len>4){//长度大于4认为是时间值
					ed = this.$api.isNumber(ed, true)? Number(ed) :ed;
					ed = new Date(ed).getFullYear();
				}else if(len<4){
					ed =Infinity
				}
				return ed
			},
			headStyle(){
				return `height:${this.setting.titleHeight};`
			},
			itemStyle(){
				let res ={};
				res["margin-top"] = (this.setting.rowSpace/2||0) +"em";
				res["margin-bottom"] = (this.setting.rowSpace/2||0) +"em";
				res["width"] = `${100/(this.setting.column)}%`;
				return this.$api.objToStr(res)
			},
			iconSetting(){
				if(this.$api.isObject(this.icon)){
					return Object.assign({},this.dicIcon,this.icon)
				}
				return this.dicIcon
			},
			prevCls(){
				return `${this.iconSetting.prevYear} ${this.iconClass||""}`
			},
			nextCls(){
				return `${this.iconSetting.nextYear} ${this.iconClass||""}`
			},
			//提交按钮禁用状态
			disabledSubmit(){
				let mode = this.setting.mode;
				if(mode=="radio"){
					return this.inValue.length <1
				}else if(mode=="checkbox"){
					let num = this.inValue.length;
					return (this.setting.min>num)||(this.max&&this.max<=num)||false
				}
				return this.inValue.length !=2
			},
			textSetting(){
				if(this.$api.isObject(this.text)){
					return Object.assign({},this.dicText,this.text)
				}
				return this.dicText
			}
		},
		methods: {
			//翻页
			turnPage(val){
				this.inPage += val;
				this.init();
				this.$emit("turnPage", this.inPage)
			},
			//生成年数据列表
			init(){
				//根据当前基准时间年生成3*5宫格，根据正负页号增减
				this.inList =[];
				let list = this.inList;
				let row = this.setting.row,
					col = this.setting.column;
				let len = row *col,
					start = this.origin -( (parseInt(row/2) - (row%2==0?1:0))*col + (parseInt(col/2) - (col%2==0?1:0)) ); //起始点
					
				//填充
				for(let i=0; i<len; i++){
					let value = start +i +this.inPage *len;
					let obj = {
						name:value,
						value
					}
					if(value==this.thisYear){
						obj["name"] = this.textSetting.thisYear
					}
					let inValue =this.inValue;
					if(inValue.includes(value)){
						obj["act"] = true
					}
					if(this.setting.mode=="range"){
						if(value>=inValue[0]&&value<=inValue[1]){
							obj["bgAct"] = true
						}
					}
					if(this.defStart>value||this.defEnd<value){
						obj["disabled"] = true
					}
					
					list.push(obj)
				}
				//检查粘连
				let radius = this.setting.radius;
				for(let i=0; i<len; i++){
					let R =[radius,radius,radius,radius],
						bgR =[0,0,0,0],
						borderColor ="transparent";
					if(list[i].act){
						borderColor =[null,null,null,null];
						if(i>0&&list[i-1].act){
							R[0] =0;
							R[3] =0;
							borderColor[3] ="transparent";
						}
						if(i<len-1&&list[i+1].act){
							R[1] =0;
							R[2] =0;
							borderColor[1] ="transparent";
						}
					}
					if(list[i].bgAct){
						if(i==0||!list[i-1].bgAct){
							bgR[0] =radius;
							bgR[3] =radius;
						}
						if(i==len-1||!list[i+1].bgAct){
							bgR[1] =radius;
							bgR[2] =radius;
						}
					}
					list[i]["radius"] =R;
					list[i]["bgRadius"] =bgR;
					list[i]["borderColor"] = borderColor;
				}
			},
			//点击年
			onClick(val){
				switch(this.setting.mode){
					case "radio":
						this.inValue =[val];
						this.$emit("change", val);
						this.$emit("input", val);
						break;
					case "checkbox":
						let idx = this.inValue.indexOf(val);
						if(idx>-1){//已选中，再次点击则删除
							this.inValue.splice(idx,1)
						}else{
							this.inValue.push(val);
							//重排序
							this.inValue.sort(function(a,b){return a-b});
						}
						this.$emit("change", this.inValue);
						this.$emit("input", this.inValue);
						break;
					case "range":
						let len = this.inValue.length;
						if(len ==0 || len >=2){//选择起点
							this.inValue = [val]
						}else{//选择终点
							this.inValue.push(val);
							//重排序
							this.inValue.sort(function(a,b){return a-b});
							this.$emit("change", this.inValue);
							this.$emit("input", this.inValue);
						}
						break;
				}
				this.init()
			},
			//点击标题
			headClick(){
				this.$emit("headClick")
			},
			//外部赋值，校验
			setValue(newVal){
				let res,
					type = this.$api.typeAsk(newVal),
					mode = this.setting.mode;
				if(mode=="radio"){
					res = type=="Array"? [newVal[0]] :[_checkValue(newVal)];
				}else if(mode=="checkbox"){
					res = type=="Array"? newVal :[newVal];
					let tempArr =[];
					for(let item of res){
						let value = _checkValue(item);
						if(value){
							tempArr.push(value)
						} 
					}
					res = tempArr;
				}else if(mode=="range"){
					res = this.$api.isArray(newVal)? [_checkValue(newVal[0]), _checkValue(newVal[1])] :[]
				}
				this.origin = res[0] ||new Date().getFullYear();
				this.inValue = res;
				function _checkValue(val){
					if(!val){
						return null
					}else if(String(val).length==4){//年份值直接取值
						return Number(val)
					}else{//其他值转时间格式
						let temp = new Date(val).getFullYear();
						return temp? temp :new Date().getFullYear()
					}
				}
				this.$emit("ready",mode=="radio"?this.inValue[0]:this.inValue);
			},
			//打开选择列表
			showSelectList(){
				this.$refs.selectList.open()
			},
			//删除元素
			delItem(val){
				let idx = this.inValue.indexOf(val);
				if(idx>-1){
					this.inValue.splice(idx,1)
				}
				this.init()
			},
			//提交事件
			submit(){
				let len = this.inValue.length;
				let res,max=this.max||0;
				switch(this.setting.mode){
					case "radio":
						if(len<1){
							this.$api.msg(this.textSetting.tipYearEmptyError, "error")
							return
						}
						res = this.inValue[0];
						break;
					case "checkbox":
						if(len<this.setting.min||(max&&len>max)){
							let msg = max? this.textSetting.tipYearMaxError :this.textSetting.tipYearMinError;
							msg = msg.replace("${min}", this.setting.min);
							msg = msg.replace("${max}", this.max);
							this.$api.msg(msg, "error")
							return
						}
						res = this.inValue;
						break;
					case "range":
						if(this.isRange&&len!=2){
							this.$api.msg(this.textSetting.tipYearRangeError, "error")
							return
						}
						res = this.inValue;
						break;
				}
				this.$emit("submit", res);
			},
		},
		watch:{
			"page":{
				handler(newVal){
					if(this.$api.isValue(newVal)){
						this.inPage = newVal;
						this.init();
					}
				}
			},
			"value":{
				handler(newVal){
					this.inPage =0;
					this.setValue(newVal);
					this.init();
				}
			}
		},
		created() {
			this.thisYear = new Date().getFullYear();
			this.inPage = this.page||0;
			this.setValue(this.value);
			this.init();
		}
	}
</script>

<style lang="scss">
.vi_year{
	.vi_year_head{
		display: flex;
		justify-content: space-between;
		align-items: center;
		padding: 0 1em;
		border-bottom: 1px solid $vi-borColor-light;
		.iconfont{
			padding: 0.35em;
		}
	}
	.vi_year_body{
		position: relative;
	}
	.vi_year_selectList{
		height: 100%;
	}
	.vi_year_selectItem{
		display: flex;
		align-items: center;
		justify-content: space-between;
		margin: 0 0.5em;
		padding: 0 0.5em;
		height: 3em;
		&:nth-child(even){
			background-color: #f8f8f8;
		}
	}
	.vi_year_list{
		padding: 0.25em 0;
		display: flex;
		flex-wrap: wrap;
	}
	.vi_year_itembox{
		position: relative;
	}
	.vi_year_item{
		position: relative;
		z-index: 1;
	}
	.vi_year_actBg{
		position: absolute;
		z-index: 0;
		top: 0;
		left: 0;
		width: 100%;
	}
	.vi_mx{
		margin: 0 0.35em;
	}
	.vi_mr{
		margin-right: 0.5em;
	}
	.vi_year_tips{
		line-height: 2.5;
		display: flex;
		align-items: center;
		.vi_year_text{
			flex-shrink: 0;
		}
	}
	.vi_month_info{
		overflow: hidden;white-space: nowrap;text-overflow: ellipsis;
	}
	.vi_inlineBlock{
		display: inline-block;
	}
}
</style>
